<template>
  <div class="video-meeting-container">
    <div id="jitsi-container" ref="jitsiContainer"></div>

    <!-- 连接状态提示 -->
    <div v-if="connectionStatus === 'connecting'" class="connection-status">
      <el-icon class="loading"><Loading /></el-icon>
      <span>正在连接会议...</span>
    </div>

    <!-- 会议控制栏 -->
    <div v-if="!isFullScreen" class="meeting-controls">
      <div class="meeting-info">
        <div class="meeting-header">
          <span class="meeting-title">{{ meetingTitle }}</span>
          <span v-if="isRecording" class="recording-indicator">
            <el-icon class="recording-icon"><VideoCamera /></el-icon>
            录制中
          </span>
        </div>
        <div class="meeting-stats">
          <span class="meeting-time">{{ formattedDuration }}</span>
          <span class="participant-count">{{ participants.length }} 人在线</span>
        </div>
      </div>

      <div class="control-buttons">
        <!-- 音频控制 -->
        <el-tooltip content="麦克风" placement="top" :show-after="500">
          <el-button :type="isMuted ? 'danger' : 'primary'" circle @click="toggleAudio">
            <el-icon><Microphone v-if="!isMuted" /><Mute v-else /></el-icon>
          </el-button>
        </el-tooltip>

        <!-- 视频控制 -->
        <el-tooltip content="摄像头" placement="top" :show-after="500">
          <el-button :type="isVideoOff ? 'danger' : 'primary'" circle @click="toggleVideo">
            <el-icon><VideoCamera v-if="!isVideoOff" /><VideoCameraFilled v-else /></el-icon>
          </el-button>
        </el-tooltip>

        <!-- 屏幕共享 -->
        <el-tooltip content="屏幕共享" placement="top" :show-after="500">
          <el-button type="primary" circle @click="toggleScreenShare">
            <el-icon><Monitor /></el-icon>
          </el-button>
        </el-tooltip>

        <!-- 设备选择 -->
        <el-dropdown trigger="click" @command="handleDeviceSelect">
          <el-button type="primary" circle>
            <el-icon><Setting /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item disabled>
                <div class="device-menu-title">音频输入</div>
              </el-dropdown-item>
              <el-dropdown-item
                v-for="device in deviceList.audioInput"
                :key="device.deviceId"
                :command="{ type: 'audioInput', id: device.deviceId }"
                :class="{ 'is-active': selectedDevices.audioInput === device.deviceId }">
                {{ device.label }}
              </el-dropdown-item>
              <el-dropdown-item divided disabled>
                <div class="device-menu-title">音频输出</div>
              </el-dropdown-item>
              <el-dropdown-item
                v-for="device in deviceList.audioOutput"
                :key="device.deviceId"
                :command="{ type: 'audioOutput', id: device.deviceId }"
                :class="{ 'is-active': selectedDevices.audioOutput === device.deviceId }">
                {{ device.label }}
              </el-dropdown-item>
              <el-dropdown-item divided disabled>
                <div class="device-menu-title">视频输入</div>
              </el-dropdown-item>
              <el-dropdown-item
                v-for="device in deviceList.videoInput"
                :key="device.deviceId"
                :command="{ type: 'videoInput', id: device.deviceId }"
                :class="{ 'is-active': selectedDevices.videoInput === device.deviceId }">
                {{ device.label }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>

        <!-- 录制控制 -->
        <el-tooltip :content="isRecording ? '停止录制' : '开始录制'" placement="top" :show-after="500">
          <el-button :type="isRecording ? 'danger' : 'primary'" circle @click="toggleRecording">
            <el-icon><VideoCamera /></el-icon>
          </el-button>
        </el-tooltip>

        <!-- 参会者列表 -->
        <el-dropdown trigger="click">
          <el-button type="primary" circle>
            <el-icon><User /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-for="p in participants" :key="p.id">
                <div class="participant-item">
                  <span class="participant-name">
                    {{ p.displayName }}
                    <el-tag v-if="p.role === 'moderator'" size="small" type="success">主持人</el-tag>
                    <el-tag v-if="p.isHandRaised" size="small" type="warning">举手</el-tag>
                  </span>
                  <div class="participant-controls">
                    <el-button v-if="p.role !== 'moderator'" size="small" type="primary" @click="grantModerator(p.id)">
                      设为主持人
                    </el-button>
                    <el-button
                      size="small"
                      :type="p.isAudioMuted ? 'danger' : 'success'"
                      @click="muteParticipant(p.id)">
                      {{ p.isAudioMuted ? '解除静音' : '静音' }}
                    </el-button>
                    <el-button size="small" type="danger" @click="kickParticipant(p.id)"> 移出会议 </el-button>
                  </div>
                </div>
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>

        <!-- 结束会议 -->
        <el-tooltip content="结束会议" placement="top" :show-after="500">
          <el-button type="danger" circle @click="endMeeting">
            <el-icon><Phone /></el-icon>
          </el-button>
        </el-tooltip>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  Microphone,
  Mute,
  VideoCamera,
  VideoCameraFilled,
  Monitor,
  Phone,
  Loading,
  Setting,
  User,
} from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'

const props = defineProps({
  roomName: {
    type: String,
    required: true,
  },
  displayName: {
    type: String,
    required: true,
  },
  meetingTitle: {
    type: String,
    default: '专家答疑',
  },
  isAudioOnly: {
    type: Boolean,
    default: false,
  },
  password: {
    type: String,
    default: '',
  },
})

const emit = defineEmits(['end-meeting', 'participant-joined', 'participant-left', 'chat-message'])
const router = useRouter()

const jitsiContainer = ref(null)
const api = ref(null)
const isMuted = ref(false)
const isVideoOff = ref(false)
const isFullScreen = ref(false)
const isRecording = ref(false)
const startTime = ref(null)
const duration = ref(0)
const participants = ref([])
const deviceList = ref({
  audioInput: [],
  audioOutput: [],
  videoInput: [],
})
const selectedDevices = ref({
  audioInput: '',
  audioOutput: '',
  videoInput: '',
})
const connectionStatus = ref('disconnected')
const reconnectAttempts = ref(0)
const MAX_RECONNECT_ATTEMPTS = 3
const formattedDuration = computed(() => {
  const minutes = Math.floor(duration.value / 60)
  const seconds = duration.value % 60
  return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
})

// 更新会议时长
let durationTimer = null
function updateDuration() {
  if (startTime.value) {
    duration.value = Math.floor((Date.now() - startTime.value) / 1000)
  }
}

onMounted(async () => {
  try {
    // 加载Jitsi Meet外部脚本
    await loadJitsiScript()

    // 初始化会议
    initJitsiMeet()

    // 开始计时
    startTime.value = Date.now()
    durationTimer = setInterval(updateDuration, 1000)
  } catch (error) {
    console.error('初始化会议失败:', error)
    ElMessage.error('初始化会议失败，请刷新页面重试')
  }
})

onBeforeUnmount(() => {
  if (api.value) {
    api.value.dispose()
  }
  if (durationTimer) {
    clearInterval(durationTimer)
  }
})

// 加载Jitsi Meet脚本
function loadJitsiScript() {
  return new Promise((resolve, reject) => {
    if (window.JitsiMeetExternalAPI) {
      resolve()
      return
    }

    const script = document.createElement('script')
    script.src = 'https://localhost:8443/external_api.js'
    script.async = true
    script.onload = resolve
    script.onerror = reject
    document.body.appendChild(script)
  })
}

// 初始化Jitsi Meet
function initJitsiMeet() {
  const domain = 'localhost:8443'
  const options = {
    roomName: props.roomName,
    width: '100%',
    height: '100%',
    parentNode: jitsiContainer.value,
    configOverwrite: {
      startWithAudioMuted: false,
      startWithVideoMuted: props.isAudioOnly,
      disableDeepLinking: true,
      prejoinPageEnabled: false,
      disableInviteFunctions: true,
      enableClosePage: true,
      enableWelcomePage: false,
      resolution: 720,
      constraints: {
        video: {
          height: {
            ideal: 720,
            max: 720,
            min: 180,
          },
        },
      },
      p2p: {
        enabled: true,
      },
    },
    interfaceConfigOverwrite: {
      TOOLBAR_BUTTONS: [
        'microphone',
        'camera',
        'desktop',
        'fullscreen',
        'fodeviceselection',
        'chat',
        'recording',
        'raisehand',
        'settings',
        'stats',
        'shortcuts',
      ],
      SHOW_JITSI_WATERMARK: false,
      SHOW_WATERMARK_FOR_GUESTS: false,
      SHOW_BRAND_WATERMARK: false,
      MOBILE_APP_PROMO: false,
      DISABLE_JOIN_LEAVE_NOTIFICATIONS: false,
      INITIAL_TOOLBAR_TIMEOUT: 20000,
      TOOLBAR_TIMEOUT: 4000,
      DEFAULT_REMOTE_DISPLAY_NAME: '参会者',
      DEFAULT_LOCAL_DISPLAY_NAME: props.displayName,
    },
    userInfo: {
      displayName: props.displayName,
    },
  }

  if (props.password) {
    options.configOverwrite.lockRoomPassword = props.password
  }

  try {
    connectionStatus.value = 'connecting'
    api.value = new window.JitsiMeetExternalAPI(domain, options)

    api.value.addEventListeners({
      videoConferenceJoined: handleVideoConferenceJoined,
      participantJoined: handleParticipantJoined,
      participantLeft: handleParticipantLeft,
      audioMuteStatusChanged: handleAudioMuteStatusChanged,
      videoMuteStatusChanged: handleVideoMuteStatusChanged,
      readyToClose: handleReadyToClose,
      screenSharingStatusChanged: handleScreenSharingStatusChanged,
      recordingStatusChanged: handleRecordingStatusChanged,
      chatUpdated: handleChatMessage,
      deviceListChanged: handleDeviceListChanged,
      connectionEstablished: handleConnectionEstablished,
      connectionFailed: handleConnectionFailed,
      participantRoleChanged: handleParticipantRoleChanged,
      audioAvailabilityChanged: handleAudioAvailabilityChanged,
      videoAvailabilityChanged: handleVideoAvailabilityChanged,
      raiseHandUpdated: handleRaiseHandUpdated,
    })
  } catch (error) {
    console.error('初始化会议失败:', error)
    handleConnectionFailed()
  }
}

// 事件处理函数
function handleVideoConferenceJoined() {
  ElMessage.success('成功加入会议')
}

function handleParticipantJoined({ id, displayName }) {
  const participant = {
    id,
    displayName: displayName || '参会者',
    role: 'participant',
    isAudioMuted: true,
    isVideoMuted: true,
    isHandRaised: false,
  }
  participants.value.push(participant)
  emit('participant-joined', participant)
  ElMessage.success(`${participant.displayName} 加入会议`)
}

function handleParticipantLeft({ id }) {
  ElMessage.info('参会者离开了会议')
}

function handleAudioMuteStatusChanged({ muted }) {
  isMuted.value = muted
}

function handleVideoMuteStatusChanged({ muted }) {
  isVideoOff.value = muted
}

function handleReadyToClose() {
  endMeeting()
}

function handleScreenSharingStatusChanged({ on }) {
  ElMessage.success(on ? '开始屏幕共享' : '结束屏幕共享')
}

function handleRecordingStatusChanged({ on, mode }) {
  isRecording.value = on
  if (on) {
    ElMessage.success(`开始${mode === 'file' ? '录制' : '直播'}`)
  } else {
    ElMessage.warning(`${mode === 'file' ? '录制' : '直播'}已停止`)
  }
}

function handleChatMessage({ message, privateMessage, nick }) {
  emit('chat-message', {
    message,
    isPrivate: privateMessage,
    sender: nick,
  })
}

function handleDeviceListChanged(devices) {
  deviceList.value = devices
}

function handleConnectionEstablished() {
  connectionStatus.value = 'connected'
  reconnectAttempts.value = 0
  ElMessage.success('会议连接已建立')
}

function handleConnectionFailed() {
  if (reconnectAttempts.value < MAX_RECONNECT_ATTEMPTS) {
    reconnectAttempts.value++
    ElMessage.warning(`连接失败，正在尝试重新连接 (${reconnectAttempts.value}/${MAX_RECONNECT_ATTEMPTS})`)
    setTimeout(() => {
      initJitsiMeet()
    }, 2000)
  } else {
    connectionStatus.value = 'disconnected'
    ElMessage.error('会议连接失败，请检查网络后重试')
    endMeeting()
  }
}

function handleParticipantRoleChanged({ id, role }) {
  const participant = participants.value.find((p) => p.id === id)
  if (participant) {
    participant.role = role
  }
}

function handleAudioAvailabilityChanged({ available }) {
  if (!available) {
    ElMessage.warning('音频设备不可用')
  }
}

function handleVideoAvailabilityChanged({ available }) {
  if (!available) {
    ElMessage.warning('视频设备不可用')
  }
}

function handleRaiseHandUpdated({ id, handRaised }) {
  const participant = participants.value.find((p) => p.id === id)
  if (participant) {
    participant.isHandRaised = handRaised
    if (handRaised) {
      ElMessage.info(`${participant.displayName} 举手请求发言`)
    }
  }
}

// 设备选择处理
async function handleDeviceSelect({ type, id }) {
  try {
    await setDevice(type, id)
    selectedDevices.value[type] = id
  } catch (error) {
    console.error('切换设备失败:', error)
    ElMessage.error('切换设备失败')
  }
}

// 控制功能
function toggleAudio() {
  api.value.executeCommand('toggleAudio')
}

function toggleVideo() {
  api.value.executeCommand('toggleVideo')
}

function toggleScreenShare() {
  api.value.executeCommand('toggleShareScreen')
}

// 设备控制功能
async function getAvailableDevices() {
  try {
    const devices = await api.value.executeCommand('getAvailableDevices')
    deviceList.value = devices
    return devices
  } catch (error) {
    console.error('获取设备列表失败:', error)
    ElMessage.error('获取设备列表失败')
  }
}

async function getCurrentDevices() {
  try {
    const devices = await api.value.executeCommand('getCurrentDevices')
    selectedDevices.value = devices
    return devices
  } catch (error) {
    console.error('获取当前设备失败:', error)
    ElMessage.error('获取当前设备失败')
  }
}

async function setDevice(deviceType, deviceId) {
  try {
    await api.value.executeCommand('setDevice', deviceType, deviceId)
    await getCurrentDevices()
    ElMessage.success('设备切换成功')
  } catch (error) {
    console.error('设备切换失败:', error)
    ElMessage.error('设备切换失败')
  }
}

// 会议控制功能
function toggleRecording() {
  if (api.value) {
    api.value.executeCommand('toggleRecording')
  }
}

function kickParticipant(participantId) {
  if (api.value) {
    api.value.executeCommand('kickParticipant', participantId)
  }
}

function grantModerator(participantId) {
  if (api.value) {
    api.value.executeCommand('grantModerator', participantId)
  }
}

function muteParticipant(participantId) {
  if (api.value) {
    api.value.executeCommand('muteParticipant', participantId)
  }
}

function sendChatMessage(message, to = null) {
  if (api.value) {
    api.value.executeCommand('sendChatMessage', message, to)
  }
}

// 修改结束会议函数
async function endMeeting() {
  try {
    if (isRecording.value) {
      await api.value.executeCommand('toggleRecording')
    }

    await ElMessageBox.confirm('确定要结束当前会议吗？', '结束会议', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })

    // 清除计时器
    if (durationTimer) {
      clearInterval(durationTimer)
      durationTimer = null
    }

    if (api.value) {
      sendChatMessage('会议即将结束，感谢参与！')

      await new Promise((resolve) => setTimeout(resolve, 1000))

      api.value.executeCommand('hangup')
      api.value.dispose()
      api.value = null
    }

    emit('end-meeting', {
      duration: duration.value,
      startTime: startTime.value,
      participants: participants.value,
    })

    router.back()
  } catch {
    // 用户取消
  }
}

// 导出方法供父组件使用
defineExpose({
  getAvailableDevices,
  getCurrentDevices,
  setDevice,
  toggleRecording,
  kickParticipant,
  grantModerator,
  muteParticipant,
  sendChatMessage,
})
</script>

<style scoped>
.video-meeting-container {
  position: relative;
  width: 100%;
  height: 100vh;
  background: #1a1a1a;
}

#jitsi-container {
  width: 100%;
  height: 100%;
}

.connection-status {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.8);
  padding: 20px 40px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 12px;
  color: #fff;
}

.loading {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.meeting-controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 20px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.meeting-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.meeting-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.meeting-title {
  color: #fff;
  font-size: 16px;
  font-weight: 500;
}

.recording-indicator {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #ff4d4f;
  font-size: 14px;
}

.recording-icon {
  animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 1;
  }
}

.meeting-stats {
  display: flex;
  gap: 12px;
  color: #e6e6e6;
  font-size: 14px;
}

.control-buttons {
  display: flex;
  gap: 16px;
}

:deep(.el-button.is-circle) {
  width: 48px;
  height: 48px;
}

:deep(.el-icon) {
  font-size: 20px;
}

.device-menu-title {
  color: #909399;
  font-size: 12px;
  padding: 0 12px;
}

.participant-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0;
}

.participant-name {
  display: flex;
  align-items: center;
  gap: 8px;
}

.participant-controls {
  display: flex;
  gap: 8px;
}

:deep(.el-dropdown-menu__item.is-active) {
  color: #409eff;
  font-weight: bold;
}
</style>
